#pragma once

#include "checks.h"
#include "log.h"

#include <stddef.h>
#include <assert.h>

#ifdef HAVE_STDINT
#include <stdint.h>
#else
// visual studio has no stdint header
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;  // NOLINT
typedef unsigned short uint16_t;  // NOLINT
typedef int int32_t;
typedef unsigned int uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
// intptr_t and friends are defined in crtdefs.h through stdio.h.
#endif

typedef uint8_t byte;

namespace l8
{

#if 0
// The USE(x) template is used to silence C++ compiler warnings
// issued for (yet) unused variables (typically parameters).
template <typename T>
static inline void USE(T) { }
#else
#define USE(x)
#endif

// typedefs
typedef byte* Address;

// function_cast<F>(addr) casts an address into a function
// of type F. Used to invoke generated code from within C.
template <typename F>
F function_cast(Address addr)
{
    return reinterpret_cast<F>(reinterpret_cast<intptr_t>(addr));
}


// arch-dependent
#if HOST_ARCH_X64
#ifdef _MSC_VER
#define UINT64_C(x)  (x ## UI64)
#define INT64_C(x)   (x ## I64)
#define PRINT_PTR_PREFIX "ll"
#else  // ! _MSC_VER
#define UINT64_C(x)  (x ## UL)
#define INT64_C(x)   (x ## L)
#define PRINT_PTR_PREFIX "l"
#endif  // _MSC_VER
#else  // HOST_ARCH_X64
#define PRINT_PTR_PREFIX ""
#endif  // HOST_ARCH_X64

// printing pointers as hex/as number
#define PRINT_xPTR PRINT_PTR_PREFIX "x"
#define PRINT_dPTR PRINT_PTR_PREFIX "d"


#ifdef HOST_ARCH_X64
const Address kZapValue =
    reinterpret_cast<Address>(UINT64_C(0xdeadbeedbeadbeed));
const Address kHandleZapValue =
    reinterpret_cast<Address>(UINT64_C(0x1baddead0baddead));
const Address kFromSpaceZapValue =
    reinterpret_cast<Address>(UINT64_C(0x1beefdad0beefdad));
#else
const Address kZapValue = reinterpret_cast<Address>(0xdeadbeed);
const Address kHandleZapValue = reinterpret_cast<Address>(0xbaddead);
const Address kFromSpaceZapValue = reinterpret_cast<Address>(0xbeefdad);
#endif


// class utility


// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName)      \
    TypeName(const TypeName&);                  \
    void operator=(const TypeName&)


// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
    TypeName();                                  \
    DISALLOW_COPY_AND_ASSIGN(TypeName)


// constants
static const int kCharSize      = sizeof(char);      // NOLINT
static const int kShortSize     = sizeof(short);     // NOLINT
static const int kIntSize       = sizeof(int);       // NOLINT
static const int kDoubleSize    = sizeof(double);    // NOLINT
static const int kPointerSize   = sizeof(void*);     // NOLINT
static const int kIntptrSize    = sizeof(intptr_t);  // NOLINT

} // namespace l8
